﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Text.RegularExpressions;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using Eneta.Portal.Common;
using Eneta.Portal.Common.Repository;
using Microsoft.SharePoint;

namespace Eneta.Portal.Profiles.Controls
{
    public class ProfileEditControl : UserControl
    {
        protected Label titleLabel;
        protected Label headerUserNameLabel;
        protected System.Web.UI.WebControls.Image titleImage;
        protected HtmlAnchor titleLink;
        protected Button editButton;

        protected HtmlGenericControl MessageBox;
        protected Label MessageLabel;

        protected HtmlGenericControl firstNameContainer;
        protected HtmlGenericControl firstNameErrorMessage;
        protected HtmlGenericControl firstNameErrorNote;
        protected TextBox firstNameField;
        protected CheckBox showFirstName;
        protected TextBox lastNameField;
        protected CheckBox showLastName;
        protected TextBox emailField;
        protected CheckBox showEmail;

        protected HtmlGenericControl interestsContainer;
        protected HtmlGenericControl interestsErrorMessage;
        protected HtmlGenericControl interestsErrorNote;
        protected CheckBoxList interestsList;

        protected TextBox aboutField;
        protected System.Web.UI.WebControls.Image profileImage;
        protected FileUpload profileImageUpload;
        protected TextBox homePageUrlField;
        protected TextBox addressField;
        protected CheckBox showAddress;
        protected TextBox phoneField;
        protected CheckBox showPhone;

        protected TextBox schoolField;
        protected CheckBox showSchool;
        protected TextBox fieldOfStudyField;
        protected CheckBox showFieldOfStudy;

        protected TextBox companyField;
        protected CheckBox showCompany;
        protected TextBox jobTitleField;
        protected CheckBox showJobTitle;

        protected CheckBox sendMsInfo;
        protected CheckBox sendEventsInfo;
        protected Button saveButton;


        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);
            saveButton.Click += SaveButtonClick;

        }



        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            HideErrors(Controls);

            var currentUser = SPContext.Current.Web.CurrentUser;

            if (currentUser == null || Item == null)
            {
                Response.Redirect("/");
                return;
            }

            if ("liveid:" + Item["SysID"].ToString().ToLower() != currentUser.LoginName.ToLower())
                if (!currentUser.IsSiteAdmin)
                {
                    Response.Redirect("/");
                    return;
                }

            Page.Title = currentUser.Name + " > Muuda profiili | Microsoft Eneta";

            MessageBox.Visible = false;

            var msg = Request.QueryString["msg"] ?? string.Empty;

            switch (msg)
            {
                case "joined":
                    MessageLabel.Text = "Aitäh Sulle, kasutaja on edukalt loodud. Palun täida oma profiil<br/>lõpuni, et osaleda Eneta portaalis täisväärtusliku liikmena.";
                    break;
                case "missingflds":
                    MessageLabel.Text = "Palun täida oma profiili kohustuslikud väljad.";
                    MessageBox.Attributes["class"] = "slide-box warning";
                    break;
                default:
                    msg = string.Empty;
                    break;
            }

            MessageBox.Visible = !string.IsNullOrEmpty(msg);
            //MessageBox.Attributes["class"] = "slide-box success";

            if (IsPostBack)
                return;
            Bind();
        }

        protected override void OnPreRender(EventArgs e)
        {
            base.OnPreRender(e);

            if (homePageUrlField.Text == string.Empty)
                homePageUrlField.Text = "http://";
            if (homePageUrlField.Text.ToLower() == "http://")
                homePageUrlField.CssClass = "text-go clear";
            else
                homePageUrlField.CssClass = "text-go";

            SetCheckStyles(Controls);
        }

        private static void SetCheckStyles(ControlCollection controls)
        {
            foreach (Control c in controls)
                if (c.GetType() == typeof(CheckBox))
                    ((CheckBox)c).InputAttributes["class"] = "choice";
                else if (c.HasControls())
                    SetCheckStyles(c.Controls);

        }
        private SPListItem _item;

        private SPListItem Item
        {
            get
            {
                if (_item != null)
                    return _item;

                var idString = Request.QueryString["profileID"];
                if (string.IsNullOrEmpty(idString))
                    return null;

                int id;
                if (!int.TryParse(idString, out id))
                    return null;

                _item = SPContext.Current.Web.Lists["ProfileList"].GetItemById(id);
                return _item;
            }
        }

        private void Bind()
        {
            var item = Item;
            headerUserNameLabel.Text = item.Title;
            titleLabel.Text = item.Title;
            titleLink.HRef = "/profile.aspx?ID=" + item.ID;

            object value = item[item.Fields.GetFieldByInternalName("Eesnimi").Id];
            if (value != null)
                firstNameField.Text = item["Eesnimi"].ToString();

            value = item[item.Fields.GetFieldByInternalName("ShowFirstName").Id];
            if (value != null)
                showFirstName.Checked = (bool)value;

            value = item[item.Fields.GetFieldByInternalName("Perekonnanimi").Id];
            if (value != null)
                lastNameField.Text = item["Perekonnanimi"].ToString();

            value = item[item.Fields.GetFieldByInternalName("ShowLastName").Id];
            if (value != null)
                showLastName.Checked = (bool)value;

            value = item[item.Fields.GetFieldByInternalName("Email").Id];
            if (value != null)
                emailField.Text = item["Email"].ToString();

            value = item[item.Fields.GetFieldByInternalName("ShowEmail").Id];
            if (value != null)
                showEmail.Checked = (bool)value;

            interestsList.Items.Clear();

            var choiceField = (SPFieldMultiChoice)item.Fields.GetFieldByInternalName("MyInterest");
            var choiceValue = new SPFieldMultiChoiceValue((string)item[item.Fields.GetFieldByInternalName("MyInterest").Id]);

            foreach (string choice in choiceField.Choices)
            {
                var listItem = new ListItem
                {
                    Text = choice,
                    Value = choice
                };

                for (var i = 0; i < choiceValue.Count; i++)
                    if (choice == choiceValue[i])
                    {
                        listItem.Selected = true;
                        break;
                    }
                interestsList.Items.Add(listItem);
            }

            value = item[item.Fields.GetFieldByInternalName("AboutMe").Id];
            if (value != null)
                aboutField.Text = value.ToString();

            var profileRepository = new UserProfileRepository(SPContext.Current.Web);
            var profile = profileRepository.GetUserProfileById(item.ID);
            titleImage.ImageUrl = profile.UserImage32x32Url; //"/_layouts/enetahandlers/userimagehandler.ashx?size=32&id=" + Item.ID;
            profileImage.ImageUrl = titleImage.ImageUrl;

            value = item[item.Fields.GetFieldByInternalName("Blog").Id];
            if (value != null)
            {
                var homePageField = new SPFieldUrlValue(value.ToString());
                homePageUrlField.Text = homePageField.Url;
            }

            value = item[item.Fields.GetFieldByInternalName("Aadress").Id];
            if (value != null)
            {
                addressField.Text = value.ToString();
            }
            value = item[item.Fields.GetFieldByInternalName("ShowAddress").Id];
            if (value != null)
            {
                showAddress.Checked = (bool)value;
            }

            value = item[item.Fields.GetFieldByInternalName("Phone").Id];
            if (value != null)
            {
                phoneField.Text = value.ToString();
            }
            value = item[item.Fields.GetFieldByInternalName("ShowPhone").Id];
            if (value != null)
            {
                showPhone.Checked = (bool)value;
            }

            value = item[item.Fields.GetFieldByInternalName("Kool").Id];
            if (value != null)
            {
                schoolField.Text = value.ToString();
            }
            value = item[item.Fields.GetFieldByInternalName("ShowSchool").Id];
            if (value != null)
            {
                showSchool.Checked = (bool)value;
            }

            value = item[item.Fields.GetFieldByInternalName("Eriala").Id];
            if (value != null)
            {
                fieldOfStudyField.Text = value.ToString();
            }
            value = item[item.Fields.GetFieldByInternalName("ShowFieldOfStudy").Id];
            if (value != null)
            {
                showFieldOfStudy.Checked = (bool)value;
            }

            value = item[item.Fields.GetFieldByInternalName("Firma").Id];
            if (value != null)
            {
                companyField.Text = value.ToString();
            }
            value = item[item.Fields.GetFieldByInternalName("ShowCompany").Id];
            if (value != null)
            {
                showCompany.Checked = (bool)value;
            }


            value = item[item.Fields.GetFieldByInternalName("JobTitle").Id];
            if (value != null)
            {
                jobTitleField.Text = value.ToString();
            }
            value = item[item.Fields.GetFieldByInternalName("ShowJobTitle").Id];
            if (value != null)
            {
                showJobTitle.Checked = (bool)value;
            }

            value = item[item.Fields.GetFieldByInternalName("SendEventsInfo").Id];
            if (value != null)
            {
                sendEventsInfo.Checked = (bool)value;
            }
            value = item[item.Fields.GetFieldByInternalName("SendMSInfo").Id];
            if (value != null)
            {
                sendMsInfo.Checked = (bool)value;
            }
        }

        private void SaveButtonClick(object sender, EventArgs e)
        {

            var errors = new Dictionary<string, string>();

            // Eesnimi
            if (string.IsNullOrEmpty(firstNameField.Text))
            {
                errors.Add("firstName", "Eesnime sisestamine on kohustuslik.");
            }
            else if (firstNameField.Text.Length < 2)
            {
                errors.Add("firstName", "Eesnime minimaalne pikkus on 2 tähemärki.");
            }
            else if (firstNameField.Text.Length > 25)
            {
                errors.Add("firstName", "Eesnime maksimaalne pikkus on 25 tähemärki.");
            }

            // Perenimi
            if (string.IsNullOrEmpty(lastNameField.Text))
            {
                errors.Add("lastName", "Perenime sisestamine on kohustuslik.");
            }
            else if (lastNameField.Text.Length < 2)
            {
                errors.Add("lastName", "Perenime minimaalne pikkus on 2 tähemärki.");
            }
            else if (lastNameField.Text.Length > 25)
            {
                errors.Add("lastName", "Perenime maksimaalne pikkus on 25 tähemärki.");
            }

            // E-mail
            var emailRegEx = @"^([0-9a-zA-Z]([-\.\w]*[0-9a-zA-Z])*@([0-9a-zA-Z][-\w]*[0-9a-zA-Z]\.)+[a-zA-Z]{2,9})$";
            if (string.IsNullOrEmpty(emailField.Text))
            {
                errors.Add("email", "E-posti aadressi sisestamine on kohustuslik.");
            }
            else if (emailField.Text.Length > 100)
            {
                errors.Add("email", "E-posti aadressi maksimaalne pikkus on 100 tähemärki.");
            }
            else if (!Regex.IsMatch(emailField.Text, emailRegEx))
            {
                errors.Add("email", "Sisesta korrektne e-posti aadress.");
            }

            // Huvid
            var selectedInterests = GetSelectedInterests();
            interestsErrorMessage.Visible = false;
            interestsErrorNote.Visible = false;
            if (selectedInterests.Length == 0)
            {
                errors.Add("interests", "Valik on kohustuslik.");
            }

            // Profiili pilt
            if (profileImageUpload.HasFile)
            {
                try
                {
                    using (var mem = new MemoryStream())
                    {
                        mem.Write(profileImageUpload.FileBytes, 0, profileImageUpload.FileBytes.Length);
                        var bmp = System.Drawing.Image.FromStream(mem);
                        bmp.Dispose();
                    }
                }
                catch
                {
                    errors.Add("photo", "Profiili pildi laadimine ebaõnnestus. Palun kontrolli, et pilt oleks korretkne!");
                }
            }

            if (errors.Count > 0)
            {
                ApplyErrors(errors);
                return;
            }

            var siteId2 = SPContext.Current.Site.ID;
            var userId = SPContext.Current.Web.CurrentUser.ID;
            var sec2 = new SPSecurity.CodeToRunElevated(() => Save(siteId2, userId));
            SPSecurity.RunWithElevatedPrivileges(sec2);

            Response.Redirect("/Lehed/profile.aspx?profileID=" + Request.QueryString["profileID"] + "&msg=saved");
        }
        private void Save(Guid siteId, int userId)
        {
            using (var xSite = new SPSite(siteId))
            {
                using (var web = xSite.OpenWeb())
                {
                    Logger.LogInfo("Save(): Starting", GetType().ToString());

                    var list = web.Lists["ProfileList"];
                    var xItem = list.GetItemById(Item.ID);
                    var xDigestSettings = xSite.WebApplication.FormDigestSettings;
                    var xSettingsEnable = xDigestSettings.Enabled;
                    xSite.AllowUnsafeUpdates = true;
                    web.AllowUnsafeUpdates = true;

                    Logger.LogInfo("Save(): Assigning values - main", GetType().ToString());

                    xItem[GetFieldId("Eesnimi")] = firstNameField.Text;
                    xItem[GetFieldId("ShowFirstName")] = showFirstName.Checked;
                    xItem[GetFieldId("Perekonnanimi")] = lastNameField.Text;
                    xItem[GetFieldId("ShowLastName")] = showLastName.Checked;
                    xItem[GetFieldId("Email")] = emailField.Text;
                    xItem[GetFieldId("ShowEmail")] = showEmail.Checked;

                    var interestsValue = new SPFieldMultiChoiceValue();
                    foreach (var interest in GetSelectedInterests())
                        interestsValue.Add(interest);
                    xItem[GetFieldId("MyInterest")] = interestsValue;
                    xItem[GetFieldId("AboutMe")] = aboutField.Text;
                    if (!string.IsNullOrEmpty(homePageUrlField.Text) && homePageUrlField.Text != "http://")
                    {
                        var url = homePageUrlField.Text;
                        if (!url.ToLower().StartsWith("http://") && !url.ToLower().StartsWith("https://"))
                            url = "http://" + url;
                        var homePageValue = new SPFieldUrlValue
                        {
                            Description = homePageUrlField.Text,
                            Url = url
                        };
                        xItem[GetFieldId("Blog")] = homePageValue;
                    }
                    else
                        xItem[GetFieldId("Blog")] = null;

                    Logger.LogInfo("Save(): Assigning values - address and phone", GetType().ToString());
                    xItem[GetFieldId("Aadress")] = addressField.Text;
                    xItem[GetFieldId("ShowAddress")] = showAddress.Checked;
                    xItem[GetFieldId("Phone")] = phoneField.Text;
                    xItem[GetFieldId("ShowPhone")] = showPhone.Checked;

                    Logger.LogInfo("Save(): Assigning values - school", GetType().ToString());
                    xItem[GetFieldId("Kool")] = schoolField.Text;
                    xItem[GetFieldId("ShowSchool")] = showSchool.Checked;
                    xItem[GetFieldId("Eriala")] = fieldOfStudyField.Text;
                    xItem[GetFieldId("ShowFieldOfStudy")] = showFieldOfStudy.Checked;

                    Logger.LogInfo("Save(): Assigning values - work", GetType().ToString());
                    xItem[GetFieldId("Firma")] = companyField.Text;
                    xItem[GetFieldId("ShowCompany")] = showCompany.Checked;
                    xItem[GetFieldId("JobTitle")] = jobTitleField.Text;
                    xItem[GetFieldId("ShowJobTitle")] = showJobTitle.Checked;

                    Logger.LogInfo("Save(): Assigning values - events and info", GetType().ToString());
                    xItem[GetFieldId("SendEventsInfo")] = sendEventsInfo.Checked;
                    xItem[GetFieldId("SendMSInfo")] = sendMsInfo.Checked;

                    if (profileImageUpload.HasFile)
                    {
                        Logger.LogInfo("Save(): Creating 32x32 image", GetType().ToString());
                        var stream = new MemoryStream();
                        ResizeImage(32, profileImageUpload.FileContent, stream);
                        var thumb = stream.ToArray();
                        stream.Dispose();

                        Logger.LogInfo("Save(): Creating 16x16 image", GetType().ToString());
                        stream = new MemoryStream();
                        ResizeImage(16, profileImageUpload.FileContent, stream);
                        var smallThumb = stream.ToArray();
                        stream.Dispose();

                        Logger.LogInfo("Save(): Creating 64x64 image", GetType().ToString());
                        stream = new MemoryStream();
                        ResizeImage(64, profileImageUpload.FileContent, stream);
                        var largeThumb = stream.ToArray();
                        stream.Dispose();

                        Logger.LogInfo("Save(): Removing attachments", GetType().ToString());
                        xItem.Attachments.RemoveAll();

                        Logger.LogInfo("Save(): Adding images as attachments", GetType().ToString());

                        var files = web.GetFolder("/SiteCollectionImages/users/").Files;
                        var filePrefix = files.Folder.Url + "/" + xItem.ID + "_";
                        files.Add(filePrefix + "16x16.png", smallThumb, true);
                        files.Add(filePrefix + "32x32.png", thumb, true);
                        files.Add(filePrefix + "64x64.png", largeThumb, true);

                        var profileRepository = new UserProfileRepository(web);
                        profileRepository.RemoveFromCache(xItem.ID);

                        //xItem.Attachments.Add("64x64.png", largeThumb);
                        //xItem.Attachments.Add("32x32.png", thumb);
                        //xItem.Attachments.Add("16x16.png", smallThumb);

                        /*var cachePrefix = "avatar:" + xItem.ID + ":";
                        Cache[cachePrefix + 16] = smallThumb;
                        Cache[cachePrefix + 32] = thumb;
                        Cache[cachePrefix + 64] = largeThumb;
                        */
                    }

                    try
                    {
                        xItem.Update();
                        xItem.ParentList.Update();


                        xDigestSettings.Enabled = xSettingsEnable;
                    }
                    catch (Exception ex)
                    {
                        Logger.LogWarning("Save(): Error saving profile", GetType().ToString());
                        Logger.LogException(ex);
                    }

                    var profRep = new UserProfileRepository(SPContext.Current.Web);
                    var fillmentPercent = profRep.GetUserProfileFillmentPercent(xItem);
                    if (xItem[GetFieldId("ProfileFilledDate")] == null)
                        if (fillmentPercent == 100)
                        {
                            xItem[GetFieldId("ProfileFilledDate")] = DateTime.Now;
                            xItem.Update();
                        }

                    var rep = new UserProfileRepository(SPContext.Current.Web);
                    try
                    {
                        SPUser user = null;
                        foreach (SPUser spuser in web.Users)
                            if (spuser.ID == userId)
                            {
                                user = spuser;
                                break;
                            }
                        if (user != null)
                        {
                            
                            var userItem = rep.GetUserProfileByUserName(user.LoginName, true);

                            Cache["User:" + user.LoginName] = userItem;
                            user.Email = emailField.Text;
                            user.Name = userItem.UserName;
                            user.Update();
                        }
                    }
                    catch (Exception ex)
                    {
                        Logger.LogInfo("Save(): error editing SP user - id: " + userId, "EnetaProfileEditPage");
                        Logger.LogException(ex);
                        throw;
                    }

                    rep.RemoveFromCache(Item.ID);
                }
            }

            _item = null;
            Response.Redirect("/editprofile.aspx?profileID=" + Request.QueryString["profileID"], false);
        }

        private Guid GetFieldId(string internalName)
        {
            try
            {
                return Item.Fields.GetFieldByInternalName(internalName).Id;
            }
            catch (Exception ex)
            {
                Logger.LogInfo("GetFieldId() Cannot find field: " + internalName, "EnetaProfileEditPage");
                Logger.LogException(ex);
                throw;
            }
        }

        private void ApplyErrors(Dictionary<string, string> errors)
        {
            if (errors == null)
                return;

            if (errors.Count > 0)
            {
                MessageLabel.Text = "Palun paranda salvestamisel tekkinud vead.";
                MessageBox.Visible = true;
                MessageBox.Attributes["class"] = "slide-box warning";
            }

            foreach (var fieldKey in errors.Keys)
            {
                var error = errors[fieldKey];
                var ctl = (HtmlGenericControl)Page.FindControl(fieldKey + "Container", true);
                if (ctl != null)
                    ctl.Attributes.Add("class", "info-row failed-info");

                ctl = (HtmlGenericControl)Page.FindControl(fieldKey + "ErrorMessage", true);
                if (ctl != null)
                    ctl.Visible = true;

                ctl = (HtmlGenericControl)Page.FindControl(fieldKey + "ErrorLabel", true);
                if (ctl != null)
                {
                    ctl.InnerText = error;
                    ctl.Visible = true;
                }
            }
        }

        private string[] GetSelectedInterests()
        {
            var interests = new List<string>();
            foreach (ListItem item in interestsList.Items)
            {
                if (item.Selected)
                    interests.Add(item.Value);
            }
            return interests.ToArray();
        }

        /*private void ResizeImage(int sideLength, Stream fromStream, Stream toStream)
        {
            var image = System.Drawing.Image.FromStream(fromStream);

            var abort = new System.Drawing.Image.GetThumbnailImageAbort(ThumbnailCallback);
            var thumbnail = image.GetThumbnailImage(sideLength, sideLength, abort, IntPtr.Zero);
            thumbnail.Save(toStream, image.RawFormat);

            thumbnail.Dispose();
            image.Dispose();
        }

        public bool ThumbnailCallback()
        {
            return false;
        }*/

        private static void ResizeImage(int sideLength, Stream fromStream, Stream toStream)
        {
            using (var image = System.Drawing.Image.FromStream(fromStream))
            using (var thumbnailBitmap = new Bitmap(sideLength, sideLength))
            {
                var a = Math.Min(image.Width, image.Height);
                var x = (image.Width - a) / 2;
                var y = (image.Height - a) / 2;

                using (var thumbnailGraph = Graphics.FromImage(thumbnailBitmap))
                {
                    thumbnailGraph.CompositingQuality = CompositingQuality.HighQuality;
                    thumbnailGraph.SmoothingMode = SmoothingMode.HighQuality;
                    thumbnailGraph.InterpolationMode = InterpolationMode.HighQualityBicubic;

                    var imageRectangle = new Rectangle(0, 0, sideLength, sideLength);
                    thumbnailGraph.DrawImage(image, imageRectangle, x, y, a, a, GraphicsUnit.Pixel);
                    thumbnailBitmap.Save(toStream, ImageFormat.Png);
                }
            }
        }

        private void HideErrors(ControlCollection ctls)
        {
            foreach (Control c in ctls)
            {
                if (c == null)
                    continue;
                if (string.IsNullOrEmpty(c.ID))
                    goto childnodes;
                if (!c.ID.EndsWith("Container") && !c.ID.EndsWith("ErrorLabel") && !c.ID.EndsWith("ErrorMessage"))
                    goto childnodes;

                c.Visible = false;

                if (c.ID.EndsWith("Container"))
                {
                    var ctl = (HtmlGenericControl)c;
                    ctl.Attributes["class"] = "info-row";
                    ctl.Visible = true;
                }

            childnodes:
                if (c.HasControls())
                    HideErrors(c.Controls);
            }
        }

    }
}
